package com.itheima.day3.stream;

import java.util.*;
import java.util.stream.Collectors;


public class C13GroupingByTest {
    record Hero(String name, int strength) {
    }

    public static void main(String[] args) {
        List<Hero> collection = List.of(
                new Hero("令狐冲", 90),
                new Hero("风清扬", 98),
                new Hero("独孤求败", 100),
                new Hero("方证", 92),
                new Hero("东方不败", 98),
                new Hero("冲虚", 90),
                new Hero("向问天", 88),
                new Hero("任我行", 92),
                new Hero("不戒", 88)
        );

        /*
         1. mapping(x->y, dc)  需求：根据名字长度分组，分组后组内只保留他们的武力值
             new Hero("令狐冲", 90)->90
             dc 下游收集器 down collector
         */
        collection.stream()
                .collect(Collectors.groupingBy(h -> h.name().length(),
                        Collectors.mapping(h -> h.strength(), Collectors.toList())));

        /*
         2. filtering(x->boolean, dc)  需求：根据名字长度分组，分组后组内过滤掉武力小于 90 的

         先过滤，再来分组收集
         collection.stream().filter(h -> h.strength() >= 90).collect(groupingBy(h -> h.name().length(), toList()));
         */
        // 在分组收集的过程中，执行过滤
        collection.stream()
                .collect(Collectors.groupingBy(h -> h.name().length(),
                        Collectors.filtering(h -> h.strength() >= 90, Collectors.toList())));

        /*
         3. flatMapping(x->substream, dc)     需求：根据名字长度分组，分组后组内保留人名，并且人名切分成单个字符
         */
//        "令狐冲".chars().mapToObj(Character::toString).forEach(System.out::println);
        collection.stream().collect(Collectors.groupingBy(h -> h.name().length(),
                Collectors.flatMapping(h -> h.name().chars().mapToObj(Character::toString), Collectors.toList())));

        /*
         4. counting() 需求：根据名字长度分组，分组后求每组个数
         */
        collection.stream().collect(Collectors.groupingBy(h -> h.name().length(), Collectors.counting()));

        /*
          5. minBy((a,b)->int) 需求：根据名字长度分组，分组后求每组武功最低的人
          6. maxBy((a,b)->int) 需求：根据名字长度分组，分组后求每组武功最高的人
         */
        collection.stream().collect(Collectors.groupingBy(h -> h.name().length(),
                Collectors.maxBy(Comparator.comparingInt(Hero::strength))));

        /*
          7. summingInt(x->int)            需求：根据名字长度分组，分组后求每组武力和
          8. averagingDouble(x->double)    需求：根据名字长度分组，分组后求每组武力平均值
         */
        collection.stream().collect(Collectors.groupingBy(h -> h.name().length(),
                Collectors.averagingDouble(h -> h.strength())));

        /*
         9. reducing(init,(p,x)->r)
        */
//        求和
        collection.stream().collect(Collectors.groupingBy(h -> h.name().length(),
                Collectors.mapping(h -> h.strength(), Collectors.reducing(0, (p, x) -> p + x))));
//        求个数
        collection.stream().collect(Collectors.groupingBy(h -> h.name().length(),
                Collectors.mapping(h -> 1, Collectors.reducing(0, (p, x) -> p + x))));

        // 求平均，缺少 finisher
        Map<Integer, double[]> collect = collection.stream().collect(Collectors.groupingBy(h -> h.name().length(),
                Collectors.mapping(h -> new double[]{h.strength(), 1},
                        Collectors.reducing(new double[]{0, 0}, (p, x) -> new double[]{p[0] + x[0], p[1] + x[1]}))));

        Map<Integer, Long> result = collection.stream()
                .collect(Collectors.groupingBy(
                        h -> h.name().length(),
                        Collectors.mapping(
                                h -> 1L,  // 每个元素映射为 1（Long 类型）
                                Collectors.reducing(0L, (a, b) -> a + b)  // 累加
                        )
                ));
    }
}
